package com.alongthink.javademo.aspect;

import com.alongthink.javademo.annotation.OperationLogDetail;
import com.alongthink.javademo.globalClass.ResultBody;
import com.alongthink.javademo.utilTools.LoggerUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;

@Aspect
@Component
public class LogAspect {
//    private static final Logger log = (Logger) LoggerFactory.getLogger("usr-op");
    /**
     * 此处的切点是注解的方式，也可以用包名的方式达到相同的效果
     * '@Pointcut("execution(* com.wwj.springboot.service.impl.*.*(..))")'
     */
    @Pointcut("@annotation(com.alongthink.javademo.annotation.OperationLogDetail)")
    public void operationLog(){

    }

    /**
     * 环绕增强，相当于MethodInterceptor
     */
    @Around("operationLog()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        ResultBody res = null;
        long time = System.currentTimeMillis();
        String timeStr2= LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"));
        try {
            res =  (ResultBody)joinPoint.proceed();
            time = System.currentTimeMillis() - time;
            return res;
        } finally {
            try {
                //方法执行完成后增加日志
//                addOperationLog(joinPoint,res,time);
                MethodSignature signature = (MethodSignature)joinPoint.getSignature();
                ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
                HttpServletRequest request = attributes.getRequest();
                OperationLogDetail annotation = signature.getMethod().getAnnotation(OperationLogDetail.class);
                String controllerPackage = request.getRequestURL().toString();
                if(res != null) {
                    String issuccess = "";
                    if ("200".equals(res.getCode())) {
                        issuccess = "成功";
                    } else {
                        issuccess = "失败";
                    }

                    LoggerUtils.info(timeStr2, issuccess, controllerPackage, Arrays.toString(joinPoint.getArgs()),
                            res.getResult()==null?"":res.getResult().toString(), res.getMessage(), String.valueOf(time)+"ms");
                }
            }catch (Exception e){
                System.out.println("LogAspect 操作失败：" + e.getMessage());
                e.printStackTrace();
            }
        }
    }

    @Before("operationLog()")
    public void doBeforeAdvice(JoinPoint joinPoint){
//        System.out.println("进入方法前执行.....");

    }

    /**
     * 处理完请求，返回内容
     * @param ret
     */
    @AfterReturning(returning = "ret", pointcut = "operationLog()")
    public void doAfterReturning(Object ret) {
//        System.out.println("方法的返回值 : " + ret);
    }

    /**
     * 后置异常通知
     */
    @AfterThrowing("operationLog()")
    public void throwss(JoinPoint jp){
//        System.out.println("方法异常时执行.....");
    }


    /**
     * 后置最终通知,final增强，不管是抛出异常或者正常退出都会执行
     */
    @After("operationLog()")
    public void after(JoinPoint jp){
//        System.out.println("方法最后执行.....");
    }
}
